#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>


typedef struct {
	GHashTable *hash;
	int accept;
} State;


State *state_new() {
	State *s = (State *)malloc(sizeof(State));
	s->hash = g_hash_table_new(NULL, NULL);
	//printf("*** Creating hash: %p\n", s->hash);
	s->accept = 0;
	return s;
}


State *state_lookup(State *state, char ch, int bCreate) {
	gpointer k = GINT_TO_POINTER((int)ch);
	//printf("state_lookup(): ch = %d [%c]\n", ch, ch);	
	//gint* k = g_new(gint, 1);
	//*k = ch;		
	//printf("k=%p,  state->hash = %p\n", k, state->hash);
	State *s = g_hash_table_lookup(state->hash, k);
	
	//printf("state_lookup(): ch = %d [%c], s(result) = %p\n", ch, ch, s);
	if (!s && bCreate) {
		s = state_new();
		g_hash_table_insert(state->hash, k, s);
	}
	return s;
}


lex_add_term(State *state, int term_id, char *text) {
	char *ptr = text, ch;
	//printf("lex_add_term(): state = %p, term_id = %d, text = '%s'\n", state, term_id, text);
	for (; ch = *ptr; ++ptr) {
		state = state_lookup(state, ch, TRUE);
	}
	if (!state->accept)
		state->accept = term_id;
	else
		fprintf(stderr, "Term %d '%s' cannot be matched.\n", term_id, text);
}

	
lex_run(State *initial, char *text) {
	State *s, *state = initial, *last_accept_state;
	char *ptr = text, ch, *last_accept_ptr, *yytext_begin_ptr, yytext[1000];
	int yytext_length;
	
	while (1) {		
		state = initial;
		last_accept_state = NULL;
		last_accept_ptr = NULL;		
		yytext_begin_ptr = ptr;
		ch = *ptr;
		if (!ch)
			break;
		//printf("Reading character: %d [%c]\n", ch, ch);
		while (ch && (s = state_lookup(state, ch, FALSE))) {
			state = s;
			++ptr;
			if (s->accept) {
				//printf("*** ACCEPT (%d) ?\n", s->accept);
				last_accept_state = s;
				last_accept_ptr = ptr;
			}
			ch = *ptr;
			//printf("   next character: %d [%c]\n", ch, ch);
			if (!ch)
				break;
		}
		//printf("finished lookahead on character: %d [%c]\n", ch, ch);
		if (!last_accept_state) {
			ptr = yytext_begin_ptr + 1;
		} else {
			//printf("Last accept state is defined! ptr = %p, last_accept_ptr = %p\n", ptr, last_accept_ptr);			
			state = last_accept_state;
			ptr = last_accept_ptr;
			/*
			yytext_length = ptr - yytext_begin_ptr;
			strncpy(yytext, yytext_begin_ptr, yytext_length);
			yytext[yytext_length] = 0;
			//printf("Match term %d: '%s'\n", state->accept, yytext);
			*/
			
			/*
			ch = *ptr;
			printf("   next character: %d [%c]\n", ch, ch);
			*ptr = 0;
			//*ptr = ch;
			*/
		}
	}
}








main() {
	State *initial = state_new();
	printf("INITIAL: %p\n", initial);
	
	FILE *f = fopen("highlight_data.txt", "r");	
	char buf[1000000];
	char *b;
	int i, n = 0, term_id;
	while (!feof(f)) {
		fgets(buf, 1000000, f);
		buf[strlen(buf) - 1] = 0;
		for (b = buf, i = 0; *b && (*b != '\t')  && (i < 20); ++b, ++i);
		if (*b != '\t')
			continue;
		*(b++) = 0;
		term_id = atoi(buf);
		lex_add_term(initial, term_id, b);
	}
	fclose(f);
	

	f = fopen("articles.txt", "r");
	while (!feof(f)) {
		fgets(buf, 1000000, f);
		//printf("\n--------------------\n");
		//lex_run(initial, buf);
	}
	fclose(f);

	
}
